SyncCatch is a debugging tool that catches synchronous File Manager and Device Manager requests made from code running as the result of an interrupt. If it catches one of these illegal synchronous requests, it drops into MacsBug with a message.
Why are synchronous File Manager and Device Manager requests made at interrupt time illegal?
Synchronous File Manager and Device Manager requests made at interrupt time can deadlock or crash the system. See the develop magazine article “Asynchronous Routines on the Macintosh” in issue 13 if you’d like more detailed information.
SyncCatch catches requests made at interrupt time with system patches that. The patches check for three conditions to determine if the request was made at interrupt time:
1. The 68K interrupt level. If the interrupt level is not zero, then interrupts are disabled and synchronous requests should be made.
2. VBL tasks are executing. The Mac OS executes VBL tasks at interrupt level zero. However, VBL tasks execute as a result of an interrupt so synchronous requests are still illegal.
3. Deferred Task Manager tasks are executing. The Mac OS executes Deferred Task Manager tasks at interrupt level zero. However, Deferred Task Manager tasks execute at interrupt time so synchronous requests are still illegal.
What should I do when SyncCatch drops into MacsBug with a message?
If it happened to me, I’d want to find out what code was making the illegal request. That way, I could tell the publisher of that code to fix the problem, or if it were my code, I could fix it before someone caught me crashing the system.
Here’s some hints you can use to find the faulty code:
1. First look at SyncCatch’s message. It’ll tell you if the illegal request was a File Manager or Device Manager request. It’ll also tell you why the synchronous request shouldn’t have been made (interrupts disabled, executing VBL tasks, or executing Deferred Tasks).
2. Look at the parameter block passed to the request using MacsBug’s DM command and the appropriate memory template. I usually start with the IOParamBlockRec template because it's pretty generic.
You type this:
DM RA0 IOParamBlockRec
MacsBug shows you something like this:
Displaying IOParamBlockRec at 03DEAFEE
03DEAFEE qLink B7EA003C is a bad pointer
03DEAFF2 qType 0005 = fsQType
03DEAFF4 ioTrap 0218 = PBCatSearchSync
03DEAFF6 ioCmdAddr FFC296DA ->
03DEAFFA ioCompletion B7EAFFFF is a bad pointer
03DEAFFE ioResult 0001
03DEB000 ioNamePtr NIL
03DEB004 ioVRefNum FF88
03DEB006 ioRefNum FFFF
03DEB008 ioVersNum #0
03DEB009 ioPermssn #0
03DEB00A ioMisc 00300000 ->
03DEB00E ioBuffer 0060FFFF ->
03DEB012 ioReqCount FFFF0000
03DEB016 ioActCount 00300000
03DEB01A ioPosMode 0000
03DEB01C ioPosOffset 000811CC
MacsBug will show you the parameter block used to make the request. SyncCatch sets up the ioTrap field the same way the File and Device Managers do, so MacsBug will show you what request was made by name.
3. Stack crawl using MacsBug’s SC7 command to find out what code called the File Manager or Device Manager.
If you’re lucky, it’ll be in code you wrote but haven’t shipped. If not, then you’ll have to look further to figure out what code made the illegal request.
Can I leave SyncCatch installed all of the time? How much does it slow my system down?
You can leave SyncCatch installed all of the time -- it shouldn’t affect performance much and from my testing with Mac OS 7.6, it looks like there is nothing in the Mac OS system code making illegal synchronous requests. Worst case, the patch code adds around fifty 68K instructions to every File Manager request and to _Read, _Write, _Control, and _Status requests made to device drivers.
I installed SyncCatch and now my system “beeps” once when it boots. How come?
You probably don’t have MacsBug installed. SyncCatch won’t install and will beep once if there’s no low-level debugger present.
Is there anything you know of that sets off SyncCatch?
Yes, using the “Force Quit” key sequence (command-option-escape) or using MacsBug’s ES command at interrupt time will set off SyncCatch because they both call ExitToShell. ExitToShell closes any files opened by the application and closes the application file. The _Close calls to the File Manager are synchronous and since they’re made at interrupt time, SyncCatch will catch them. In general, force quitting an application should only be done if the application has hung or crashed, and then, you should probably restart your system as soon as possible because ExitToShell performs all sorts of things that should really only be done at non-interrupt time.